﻿using DependencyInjectionHelperLib.Attributes;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;

namespace DependencyInjectionHelperLib.Navigation
{
    /// <summary>
    /// 导航对象提供者，用于存储和检索导航对象。
    /// 内部使用不暴露给外界
    /// </summary>
    internal sealed class NavigationObjectProvider : INavigationObjectProvider
    {
        private IServiceCollection _serviceCollection;
        private IServiceProvider _serviceProvider;
        private Dictionary<string, Type> _navigationTypes = new Dictionary<string, Type>();

        internal NavigationObjectProvider(IServiceCollection serviceCollection, IServiceProvider serviceProvider)
        {
            _serviceCollection = serviceCollection;
            _serviceProvider = serviceProvider;
            _navigationTypes = GetNavigationTypes(serviceCollection, serviceProvider);
        }

        private Dictionary<string, Type> GetNavigationTypes(IServiceCollection serviceCollection, IServiceProvider serviceProvider)
        {
            return serviceCollection
                .Where(d => d.ServiceType.GetCustomAttribute<DIRegistrationAttribute>() != null)
                .Select(d => d.ServiceType)
                .Where(d => !string.IsNullOrEmpty(d.GetCustomAttribute<DIRegistrationAttribute>()!.PageKey))
                .ToDictionary(type => type.GetCustomAttribute<DIRegistrationAttribute>()!.PageKey);
        }

        /// <summary>
        /// 根据键获取导航对象。
        /// </summary>
        /// <typeparam name="T">导航对象的类型。</typeparam>
        /// <param name="pageKey">导航对象的键。</param>
        /// <returns>找到的导航对象，如果未找到则返回null。</returns>
        /// <exception cref="KeyNotFoundException">当使用指定的键找不到导航对象时引发。</exception>
        public T? GetNavigationObject<T>(string pageKey)
            where T : class
        {
            if (_navigationTypes.TryGetValue(pageKey, out Type? pageKeyType))
            {
                if (Equals(pageKeyType, typeof(T)))
                {
                    return _serviceProvider.GetRequiredService<T>();
                }
                else
                {
                    throw new KeyNotFoundException($"Navigation object is not type: '{typeof(T)}'.");
                }
            }

            throw new KeyNotFoundException($"Navigation object with key '{pageKey}' not found.");
        }
    }
}